package com.xm.rsi.utils;

import com.xm.rsi.common.ErrorCode;
import com.xm.rsi.exception.BusinessException;
import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class FileReader {

    public static List<String> readTxt(File file) {
        List<String> txt = new ArrayList<>();
        try {
            BufferedReader reader = new BufferedReader(new java.io.FileReader(file));
            String line;
            while ((line = reader.readLine()) != null) {
                txt.add(line);
            }
            reader.close();
            return txt;
        } catch (IOException e) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "读取txt文件异常");
        }
    }

    public static String readWordFile(File file) {
        try (FileInputStream fis = new FileInputStream(file);
             XWPFDocument document = new XWPFDocument(fis);
             XWPFWordExtractor extractor = new XWPFWordExtractor(document)) {
            return extractor.getText();
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "读取docx文件异常");
        }
    }

    public static Date getDate(String info, String tifName) {
        String[] lines = info.split("\n");
        for (String line : lines) {
            if (line.contains(tifName)) {
                String dateString = line.split("\t")[1];
                String pattern = "dd MMM yyyy HH:mm:ss.SSS";
                String newPattern = "yyyy-MM-dd HH:mm:ss";

                SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.ENGLISH); // 设置解析器的语言环境为英语
                SimpleDateFormat newSdf = new SimpleDateFormat(newPattern);
                sdf.setLenient(false); // 设置严格解析模式

                try {
                    Date date = sdf.parse(dateString);
                    String newDateString = newSdf.format(date);
                    return newSdf.parse(newDateString);
                } catch (Exception e) {
                    throw new BusinessException(ErrorCode.OPERATION_ERROR, "日期格式异常");
                }
            }
        }
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "未匹配到日期");
    }

    public static String isCompressedFile(String filePath) {
        String[] compressedExtensions = {".zip", ".rar", ".tar.gz", ".7z"}; // 压缩包扩展名
        for (String extension : compressedExtensions) {
            if (filePath.toLowerCase().endsWith(extension)) {
                return extension;
            }
        }
        return null;
    }

    public static void unzip(File file, String to) {
        //判断生成目录是否生成，如果没有就创建
        try (ZipFile zipFile = new ZipFile(file, Charset.forName("gbk"))) {
            //创建输出目录
            createDirectory(to, null);
            Enumeration<? extends ZipEntry> enums = zipFile.entries();
            while (enums.hasMoreElements()) {
                ZipEntry entry = enums.nextElement();
                if (entry.isDirectory()) {
                    //创建空目录
                    createDirectory(to, entry.getName());
                } else {
                    try (InputStream in = zipFile.getInputStream(entry)) {
                        try (OutputStream out = Files.newOutputStream(new File(to + File.separator + entry.getName()).toPath())) {
                            int length;
                            byte[] b = new byte[2048];
                            while ((length = in.read(b)) != -1) {
                                out.write(b, 0, length);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "解压文件异常");
        }
    }


    public static void unRar(File rarPath, String dstDirectoryPath) throws Exception {
        RandomAccessFile randomAccessFile;
        // 第一个参数是需要解压的压缩包路径，第二个参数参考JdkAPI文档的RandomAccessFile
        //r代表以只读的方式打开文本，也就意味着不能用write来操作文件
        randomAccessFile = new RandomAccessFile(rarPath, "r");
        IInArchive archive = SevenZip.openInArchive(null, // null - autodetect
                new RandomAccessFileInStream(randomAccessFile));
        int[] in = new int[archive.getNumberOfItems()];
        for (int i = 0; i < in.length; i++) {
            in[i] = i;
        }
        archive.extract(in, false, new ExtractCallback(archive, dstDirectoryPath));
        archive.close();
        randomAccessFile.close();
    }

    public static void unTarGz(File file, String dstDirectoryPath) throws Exception {
        try (TarArchiveInputStream tarIn = new TarArchiveInputStream(
                new GzipCompressorInputStream(
                        new BufferedInputStream(
                                Files.newInputStream(file.toPath()))))) {
            //创建输出目录
            createDirectory(dstDirectoryPath, null);
            TarArchiveEntry entry;
            while ((entry = tarIn.getNextTarEntry()) != null) {
                //是目录
                if (entry.isDirectory()) {
                    //创建空目录
                    createDirectory(dstDirectoryPath, entry.getName());
                } else {
                    //是文件
                    try (OutputStream out = Files.newOutputStream(new File(dstDirectoryPath + File.separator + entry.getName()).toPath())) {
                        int length;
                        byte[] b = new byte[2048];
                        while ((length = tarIn.read(b)) != -1) {
                            out.write(b, 0, length);
                        }
                    }
                }
            }
        }
    }

    public static void un7z(File file, String dstDirectoryPath) {
        //开始解压
        try {
            SevenZFile sevenZFile = new SevenZFile(file);
            SevenZArchiveEntry entry;
            while ((entry = sevenZFile.getNextEntry()) != null) {
                if (entry.isDirectory()) {
                    continue;
                }
                File curfile = new File(dstDirectoryPath, entry.getName());
                File parent = curfile.getParentFile();
                if (!parent.exists()) {
                    parent.mkdirs();
                }
                FileOutputStream out = new FileOutputStream(curfile);
                byte[] content = new byte[(int) entry.getSize()];
                sevenZFile.read(content, 0, content.length);
                out.write(content);
                out.close();
            }
        } catch (IOException e) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "解压文件异常");
        }
    }


    public static void createDirectory(String outputDir, String subDir) {
        File file = new File(outputDir);
        //子目录不为空
        if (!(subDir == null || subDir.trim().isEmpty())) {
            file = new File(outputDir + File.separator + subDir);
        }
        if (!file.exists()) {
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            file.mkdirs();
        }
    }

    public static void deleteFile(File file, File tempFile) {
        if (tempFile != null)
            tempFile.delete();
        if (file != null) {
            File[] files = file.listFiles();
            if (files == null)
                return;
            for (File f : files) {
                if (f.isDirectory()) {
                    deleteFile(f, null);
                } else {
                    f.delete();
                }
            }
            file.delete();
        }
    }

}
